home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / music.c < prev    next >
C/C++ Source or Header  |  1992-12-22  |  14KB  |  557 lines

  1. /*    SCCS Id: @(#)music.c    3.1    92/11/26    */
  2. /*     Copyright (c) 1989 by Jean-Christophe Collet */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  * This file contains the different functions designed to manipulate the
  7.  * musical instruments and their various effects.
  8.  *
  9.  * Actually the list of instruments / effects is :
  10.  *
  11.  * (wooden) flute    may calm snakes if player has enough dexterity
  12.  * magic flute        may put monsters to sleep:  area of effect depends
  13.  *            on player level.
  14.  * (tooled) horn    Will awaken monsters:  area of effect depends on player
  15.  *            level.  May also scare monsters.
  16.  * fire horn        Acts like a wand of fire.
  17.  * frost horn        Acts like a wand of cold.
  18.  * bugle        Will awaken soldiers (if any):  area of effect depends
  19.  *            on player level.
  20.  * (wooden) harp    May calm nymph if player has enough dexterity.
  21.  * magic harp        Charm monsters:  area of effect depends on player
  22.  *            level.
  23.  * (leather) drum    Will awaken monsters like the horn.
  24.  * drum of earthquake    Will initiate an earthquake whose intensity depends
  25.  *            on player level.  That is, it creates ramdom pits
  26.  *            called here chasms.
  27.  */
  28.  
  29. #include "hack.h"
  30.  
  31. static void FDECL(awaken_monsters,(int));
  32. static void FDECL(put_monsters_to_sleep,(int));
  33. static void FDECL(charm_snakes,(int));
  34. static void FDECL(calm_nymphs,(int));
  35. static void FDECL(charm_monsters,(int));
  36. static void FDECL(do_earthquake,(int));
  37. static int FDECL(do_improvisation,(struct obj *));
  38.  
  39. /*
  40.  * Wake every monster in range...
  41.  */
  42.  
  43. static void
  44. awaken_monsters(distance)
  45. int distance;
  46. {
  47.     register struct monst *mtmp = fmon;
  48.  
  49.     while(mtmp) {
  50.         if (distu(mtmp->mx, mtmp->my) < distance/3) {
  51.             /* May scare some monsters */
  52.             if (!resist(mtmp, SCROLL_CLASS, 0, NOTELL))
  53.               mtmp->mflee = 1;
  54.         } else if (distu(mtmp->mx, mtmp->my) < distance) {
  55.             mtmp->msleep = 0;
  56.             mtmp->mcanmove = 1;
  57.             mtmp->mfrozen = 0;
  58.         }
  59.         mtmp = mtmp->nmon;
  60.     }
  61. }
  62.  
  63. /*
  64.  * Make monsters fall asleep.  Note that they may resist the spell.
  65.  */
  66.  
  67. static void
  68. put_monsters_to_sleep(distance)
  69. int distance;
  70. {
  71.     register struct monst *mtmp = fmon;
  72.  
  73.     while(mtmp) {
  74.           if (distu(mtmp->mx, mtmp->my) < distance)
  75.             if(mtmp->mcanmove && !resist(mtmp, WAND_CLASS, 0, NOTELL))
  76.               mtmp->mcanmove = mtmp->mfrozen = 0;
  77.         mtmp = mtmp->nmon;
  78.     }
  79. }
  80.  
  81. /*
  82.  * Charm snakes in range.  Note that the snakes are NOT tamed.
  83.  */
  84.  
  85. static void
  86. charm_snakes(distance)
  87. int distance;
  88. {
  89.     register struct monst *mtmp = fmon;
  90.  
  91.     while (mtmp) {
  92.         if (mtmp->data->mlet == S_SNAKE &&
  93.             distu(mtmp->mx, mtmp->my) < distance) {
  94.             mtmp->mpeaceful = 1;
  95.             if (cansee(mtmp->mx, mtmp->my))
  96.                 pline(
  97.  "%s freezes and sways with the music, then seems quieter.", Monnam(mtmp));
  98.         }
  99.         mtmp = mtmp->nmon;
  100.     }
  101. }
  102.  
  103. /*
  104.  * Calm nymphs in range.
  105.  */
  106.  
  107. static void
  108. calm_nymphs(distance)
  109. int distance;
  110. {
  111.     register struct monst *mtmp = fmon;
  112.  
  113.     while (mtmp) {
  114.         if (mtmp->data->mlet == S_NYMPH &&
  115.             distu(mtmp->mx, mtmp->my) < distance) {
  116.             mtmp->mpeaceful = 1;
  117.             if (cansee(mtmp->mx, mtmp->my))
  118.                 pline(
  119.  "%s listens cheerfully to the music, then seems quieter.", Monnam(mtmp));
  120.         }
  121.         mtmp = mtmp->nmon;
  122.     }
  123. }
  124.  
  125. /* Awake only soldiers of the level. */
  126.  
  127. void
  128. awaken_soldiers() {
  129. #ifdef ARMY
  130.     register struct monst *mtmp = fmon;
  131.  
  132.     while(mtmp) {
  133.         if (is_mercenary(mtmp->data) && mtmp->data != &mons[PM_GUARD]) {
  134.         mtmp->mpeaceful = mtmp->msleep = 0;
  135.         mtmp->mcanmove = 1;
  136.         if (canseemon(mtmp))
  137.             pline("%s is now ready for battle!", Monnam(mtmp));
  138.         else
  139.             Norep("You hear the sound of battle gear being readied.");
  140.         }
  141.         mtmp = mtmp->nmon;
  142.     }
  143. #endif /* ARMY */
  144. }
  145.  
  146. /* Charm monsters in range.  Note that they may resist the spell. */
  147.  
  148. static void
  149. charm_monsters(distance)
  150. int distance;
  151. {
  152.     register struct monst *mtmp = fmon, *mtmp2;
  153.  
  154.     while(mtmp) {
  155.         mtmp2 = mtmp->nmon;
  156.         if (distu(mtmp->mx, mtmp->my) <= distance)
  157.             if(!resist(mtmp, SCROLL_CLASS, 0, NOTELL))
  158.             (void) tamedog(mtmp, (struct obj *) 0);
  159.         mtmp = mtmp2;
  160.     }
  161.  
  162. }
  163.  
  164. /* Generate earthquake :-) of desired force.
  165.  * That is:  create random chasms (pits).
  166.  */
  167.  
  168. static void
  169. do_earthquake(force)
  170. int force;
  171. {
  172.     register int x,y;
  173.     struct monst *mtmp;
  174.     struct obj *otmp;
  175.     struct trap *chasm;
  176.     int start_x, start_y, end_x, end_y;
  177.  
  178.     start_x = u.ux - (force * 2);
  179.     start_y = u.uy - (force * 2);
  180.     end_x = u.ux + (force * 2);
  181.     end_y = u.uy + (force * 2);
  182.     if (start_x < 1) start_x = 1;
  183.     if (start_y < 1) start_y = 1;
  184.     if (end_x >= COLNO) end_x = COLNO - 1;
  185.     if (end_y >= ROWNO) end_y = ROWNO - 1;
  186.     for (x=start_x; x<=end_x; x++) for (y=start_y; y<=end_y; y++) {
  187.         if (mtmp = m_at(x,y)) {
  188.         if (mtmp->mundetected && is_hider(mtmp->data)) {
  189.             mtmp->mundetected = 0;
  190.             if (cansee(x,y))
  191.             pline("%s is shaken loose from the ceiling!",
  192.                                 Amonnam(mtmp));
  193.             else
  194.             You("hear a thumping sound.");
  195.             if (x==u.ux && y==u.uy)
  196.             You("easily dodge the falling %s.",
  197.                                 mon_nam(mtmp));
  198.             newsym(x,y);
  199.         }
  200.         }
  201.         if (!rn2(14 - force)) switch (levl[x][y].typ) {
  202.           case FOUNTAIN : /* Make the fountain disappear */
  203.             if (cansee(x,y))
  204.                 pline("The fountain falls into a chasm.");
  205.             goto do_pit;
  206. #ifdef SINKS
  207.           case SINK :
  208.             if (cansee(x,y))
  209.                 pline("The kitchen sink falls into a chasm.");
  210.             goto do_pit;
  211. #endif
  212.           case ALTAR :
  213.             if (cansee(x,y))
  214.                 pline("The altar falls into a chasm.");
  215.             goto do_pit;
  216.           case THRONE :
  217.             if (cansee(x,y))
  218.                 pline("The throne falls into a chasm.");
  219.             /* Falls into next case */
  220.           case ROOM :
  221.           case CORR : /* Try to make a pit */
  222. do_pit:            chasm = maketrap(x,y,PIT);
  223.             chasm->tseen = 1;
  224.  
  225.             levl[x][y].doormask = 0;
  226.  
  227.             mtmp = m_at(x,y);
  228.  
  229.             if (otmp = sobj_at(BOULDER, x, y)) {
  230.             if (cansee(x, y))
  231.                pline("KADOOM! The boulder falls into a chasm%s!",
  232.                   ((x == u.ux) && (y == u.uy)) ? " below you" : "");
  233.             if (mtmp)
  234.                 mtmp->mtrapped = 0;
  235.             freeobj(otmp);
  236.             (void) flooreffects(otmp, x, y, "");
  237.             break;
  238.             }    
  239.  
  240.             /* We have to check whether monsters or player
  241.                falls in a chasm... */
  242.  
  243.             if (mtmp) {
  244.             if(!is_flyer(mtmp->data) && !is_clinger(mtmp->data)) {
  245.                 mtmp->mtrapped = 1;
  246.                 if(cansee(x,y))
  247.                 pline("%s falls into a chasm!", Monnam(mtmp));
  248.                 else if (flags.soundok && humanoid(mtmp->data))
  249.                 You("hear a scream!");
  250.                 if ((mtmp->mhp -= rnd(6)) <= 0) {
  251.                 if(!cansee(x,y))
  252.                     pline("It is destroyed!");
  253.                 else {
  254.                     You("destroy %s!", mtmp->mtame ?
  255.                     x_monnam(mtmp, 0, "poor", 0) :
  256.                     mon_nam(mtmp));
  257.                 }
  258.                 xkilled(mtmp,0);
  259.                 }
  260.             }
  261.             } else if (x == u.ux && y == u.uy) {
  262.                 if (Levitation
  263. #ifdef POLYSELF
  264.                 || is_flyer(uasmon) || is_clinger(uasmon)
  265. #endif
  266.                 ) {
  267.                     pline("A chasm opens up under you!");
  268.                     You("don't fall in!");
  269.                 } else {
  270.                     You("fall into a chasm!");
  271.                     u.utrap = rn1(6,2);
  272.                     u.utraptype = TT_PIT;
  273.                     losehp(rnd(6),"fell into a chasm",
  274.                     NO_KILLER_PREFIX);
  275.                     selftouch("Falling, you");
  276.                 }
  277.             } else newsym(x,y);
  278.             break;
  279.           case DOOR : /* Make the door collapse */
  280.             if (levl[x][y].doormask == D_NODOOR) break;
  281.             if (cansee(x,y))
  282.             pline("The door collapses.");
  283.             levl[x][y].doormask = D_NODOOR;
  284.             newsym(x,y);
  285.             break;
  286.         }
  287.     }
  288. }
  289.  
  290. /*
  291.  * The player is trying to extract something from his/her instrument.
  292.  */
  293.  
  294. static int
  295. do_improvisation(instr)
  296. struct obj *instr;
  297. {
  298.     int damage;
  299.  
  300. #ifdef MAC
  301.     mac_speaker ( instr , "C" ) ;
  302. #endif
  303.  
  304.     if (Confusion)
  305.       pline("What you produce is quite far from music...");
  306.     else
  307.       You("start playing %s.", the(xname(instr)));
  308.     switch (instr->otyp) {
  309.           case WOODEN_FLUTE:    /* May charm snakes */
  310.         if (rn2(ACURR(A_DEX)) + u.ulevel > 25)
  311.           charm_snakes((int)u.ulevel*3);
  312.         exercise(A_DEX, TRUE);
  313.         break;
  314.           case MAGIC_FLUTE: /* Make monster fall asleep */
  315.         if (instr->spe > 0) {
  316.             instr->spe--;
  317.             You("produce soft music.");
  318.             put_monsters_to_sleep((int)u.ulevel*5);
  319.         }
  320.         exercise(A_DEX, TRUE);
  321.         break;
  322.           case TOOLED_HORN:    /* Awaken monsters or scare monsters */
  323.         You("produce a frightful, grave sound.");
  324.         awaken_monsters((int)u.ulevel*30);
  325.         exercise(A_WIS, FALSE);
  326.         break;
  327.           case FROST_HORN:    /* Idem wand of cold */
  328.           case FIRE_HORN:    /* Idem wand of fire */
  329.         if (instr->spe > 0) {
  330.             instr->spe--;
  331.             if (!getdir(NULL)) {
  332.                 if (!Blind)
  333.                     pline("%s glows then fades.",
  334.                       The(xname(instr)));
  335.             } else {
  336.                 if (!u.dx && !u.dy && !u.dz) {
  337.                     if((damage = zapyourself(instr)))
  338.                       losehp(damage,
  339.         self_pronoun("using a magical horn on %sself", "him"),
  340.                       NO_KILLER_PREFIX);
  341.                     makeknown(instr->otyp);
  342.                     return(2);
  343.                 }
  344.                 buzz((instr->otyp == FROST_HORN) ? AD_COLD-1 : AD_FIRE-1, rn1(6,6), u.ux, u.uy, u.dx, u.dy);
  345.                 makeknown(instr->otyp);
  346.                 return(2);
  347.             }
  348.         }
  349.         break;
  350.           case BUGLE:    /* Awaken & attract soldiers */
  351.         You("extract a loud noise from %s.", the(xname(instr)));
  352.         awaken_soldiers();
  353.         exercise(A_WIS, FALSE);
  354.         break;
  355.           case WOODEN_HARP:    /* May calm Nymph */
  356.         if (rn2(ACURR(A_DEX)) + u.ulevel > 25)
  357.           calm_nymphs((int)u.ulevel*3);
  358.         exercise(A_DEX, TRUE);
  359.         break;
  360.           case MAGIC_HARP:    /* Charm monsters */
  361.         if (instr->spe > 0) {
  362.             pline("%s produces very attractive music.",
  363.                   The(xname(instr)));
  364.             instr->spe--;
  365.             charm_monsters(((int)u.ulevel - 1) / 3 + 1);
  366.         }
  367.         exercise(A_DEX, TRUE);
  368.         break;
  369.           case LEATHER_DRUM:    /* Awaken monsters */
  370.         You("beat a deafening row!");
  371.         awaken_monsters((int)u.ulevel * 40);
  372.         exercise(A_WIS, FALSE);
  373.         break;
  374.           case DRUM_OF_EARTHQUAKE:    /* create several pits */
  375.         if (instr->spe > 0) {
  376.             You("produce a heavy, thunderous rolling!");
  377.             pline("The entire dungeon is shaking around you!");
  378.             instr->spe--;
  379.             do_earthquake(((int)u.ulevel - 1) / 3 + 1);
  380.             makeknown(DRUM_OF_EARTHQUAKE);
  381.         }
  382.         break;
  383.           default:
  384.         impossible("What a weird instrument (%d)!",instr->otyp);
  385.         break;
  386.     }
  387.     return (2);        /* That takes time */
  388. }
  389.  
  390. #ifdef SYSV386MUSIC
  391. /*
  392.  * Play audible music on the machine's speaker if appropriate.
  393.  */
  394.  
  395. static int
  396. atconsole()
  397. {
  398.     /*
  399.      * Kluge alert: This code assumes that your [34]86 has no X terminals
  400.      * attached and that the console tty type is AT386 (this is always true
  401.      * under AT&T UNIX for these boxen). The theory here is that your remote
  402.      * ttys will have terminal type `ansi' or something else other than
  403.      * `AT386' or `xterm'. We'd like to do better than this, but testing
  404.      * to see if we're running on the console physical terminal is quite
  405.      * difficult given the presence of virtual consoles and other modern
  406.      * UNIX impedimenta...
  407.      */
  408.     char    *termtype = getenv("TERM");
  409.  
  410.      return(!strcmp(termtype, "AT386") || !strcmp(termtype, "xterm"));
  411. }
  412.  
  413. static void
  414. speaker(instr, buf)
  415. struct obj *instr;
  416. char    *buf;
  417. {
  418.     /*
  419.      * For this to work, you need to have installed the PD speaker-control
  420.      * driver for PC-compatible UNIX boxes that I (eric@snark.uu.net)
  421.      * posted to comp.sources.unix in Feb 1990. A copy may be included
  422.      * with your nethack distribution.
  423.      */
  424.     int    fd;
  425.  
  426.     if ((fd = open("/dev/speaker", 1)) != -1)
  427.     {
  428.     /* emit a prefix to modify instrumental `timbre' */
  429.     switch (instr->otyp)
  430.     {
  431.     case WOODEN_FLUTE:
  432.     case MAGIC_FLUTE:
  433.         (void) write(fd, ">ol", 1); /* up one octave & lock */
  434.         break;
  435.     case TOOLED_HORN:
  436.     case FROST_HORN:
  437.     case FIRE_HORN:
  438.         (void) write(fd, "<<ol", 2); /* drop two octaves & lock */
  439.         break;
  440.     case BUGLE:
  441.         (void) write(fd, "ol", 2); /* octave lock */
  442.         break;
  443.     case WOODEN_HARP:
  444.     case MAGIC_HARP:
  445.         (void) write(fd, "l8mlol", 4); /* fast, legato, octave lock */
  446.         break;
  447.     }
  448.     (void) write(fd, buf, strlen(buf));
  449.     (void) close(fd);
  450.     }
  451. }
  452. #endif /* SYSV386MUSIC */
  453.  
  454. /*
  455.  * So you want music...
  456.  */
  457.  
  458. int
  459. do_play_instrument(instr)
  460. struct obj *instr;
  461. {
  462.     char buf[BUFSZ], *s, c = 'y';
  463.     int x,y;
  464.     boolean ok;
  465.  
  466.     if (Underwater) {
  467.     You("can't play music underwater!");
  468.     return(0);
  469.     }
  470.     if (instr->otyp != LEATHER_DRUM && instr->otyp != DRUM_OF_EARTHQUAKE) {
  471.     c = yn("Improvise?");
  472.     }
  473.     if (c == 'n') {
  474.     getlin("What tune are you playing? [what 5 notes]", buf);
  475.     for (s=buf; *s; s++) *s = highc(*s);
  476.     You("extract a strange sound from %s!", the(xname(instr)));
  477. #ifdef SYSV386MUSIC 
  478.     /* if user is at the console, play through the console speaker */
  479.     if (atconsole())
  480.         speaker(instr, buf);
  481. #endif /* SYSV386MUSIC */
  482. #ifdef MAC
  483.     mac_speaker ( instr , buf ) ;
  484. #endif
  485.     /* Check if there was the Stronghold drawbridge near
  486.      * and if the tune conforms to what we're waiting for.
  487.      */
  488.     if(Is_stronghold(&u.uz)) {
  489.         exercise(A_WIS, TRUE);        /* just for trying */
  490.         if(!strcmp(buf,tune)) {
  491.         /* Search for the drawbridge */
  492.         for(y=u.uy-1; y<=u.uy+1; y++)
  493.             for(x=u.ux-1;x<=u.ux+1;x++)
  494.             if(isok(x,y))
  495.             if(find_drawbridge(&x,&y)) {
  496.                 if(levl[x][y].typ == DRAWBRIDGE_DOWN)
  497.                 close_drawbridge(x,y);
  498.                 else
  499.                 open_drawbridge(x,y);
  500.                 return 0;
  501.             }
  502.         } else if(flags.soundok) {
  503.         if (u.uevent.uheard_tune < 1) u.uevent.uheard_tune = 1;
  504.         /* Okay, it wasn't the right tune, but perhaps
  505.          * we can give the player some hints like in the
  506.          * Mastermind game */
  507.         ok = FALSE;
  508.         for(y = u.uy-1; y <= u.uy+1 && !ok; y++)
  509.             for(x = u.ux-1; x <= u.ux+1 && !ok; x++)
  510.             if(isok(x,y))
  511.             if(IS_DRAWBRIDGE(levl[x][y].typ) ||
  512.                is_drawbridge_wall(x,y) >= 0)
  513.                 ok = TRUE;
  514.         if(ok) { /* There is a drawbridge near */
  515.             int tumblers, gears;
  516.             boolean matched[5];
  517.  
  518.             tumblers = gears = 0;
  519.             for(x=0; x < 5; x++)
  520.             matched[x] = FALSE;
  521.  
  522.             for(x=0; x < (int)strlen(buf); x++)
  523.             if(x < 5) {
  524.                 if(buf[x] == tune[x]) {
  525.                 gears++;
  526.                 matched[x] = TRUE;
  527.                 } else
  528.                 for(y=0; y < 5; y++)
  529.                     if(!matched[y] &&
  530.                        buf[x] == tune[y] &&
  531.                        buf[y] != tune[y]) {
  532.                     tumblers++;
  533.                     matched[y] = TRUE;
  534.                     break;
  535.                     }
  536.             }
  537.             if(tumblers)
  538.             if(gears)
  539.                 You("hear %d tumbler%s click and %d gear%s turn.",
  540.                 tumblers, plur(tumblers), gears, plur(gears));
  541.             else
  542.                 You("hear %d tumbler%s click.",
  543.                 tumblers, plur(tumblers));
  544.             else if(gears) {
  545.             You("hear %d gear%s turn.", gears, plur(gears));
  546.             if (gears == 5) u.uevent.uheard_tune = 2;
  547.             }
  548.         }
  549.         }
  550.       }
  551.     return 1;
  552.     } else
  553.         return do_improvisation(instr);
  554. }
  555.  
  556. /*music.c*/
  557.